﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace AppToolkit.WPF.UI.Behaviors
{
    /// <summary>
    /// Allows binding a keyboard shortcut to a command implementation in ViewModel.
    /// </summary>
    /// <example>
    /// 
    /// </example>
    public sealed class KeyboardShortcutBehavior : Behavior<Control>
    {
        private KeyBinding _keyBinding;

        /// <summary>
        /// The <see cref="Command" /> dependency property's name.
        /// </summary>
        public const string CommandPropertyName = "Command";

        /// <summary>
        /// Gets or sets the value of the <see cref="Command" />
        /// property. This is a dependency property.
        /// </summary>
        public ICommand Command
        {
            get
            {
                return (ICommand)GetValue(CommandProperty);
            }
            set
            {
                SetValue(CommandProperty, value);
            }
        }

        /// <summary>
        /// Identifies the <see cref="Command" /> dependency property.
        /// </summary>
        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
            CommandPropertyName,
            typeof(ICommand),
            typeof(KeyboardShortcutBehavior),
            new UIPropertyMetadata(null));

        /// <summary>
        /// Specify ModifierKeys for the shortcut
        /// </summary>
        public ModifierKeys ModifierKeys { get; set; }

        /// <summary>
        /// Specify Keys for the shortcut
        /// </summary>
        public Key Key { get; set; }


        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        /// <remarks>
        /// Override this to hook up functionality to the AssociatedObject.
        /// </remarks>
        protected override void OnAttached()
        {
            if (Command == null)
            {
                Trace.TraceError("KeyboardShortcutBehavior: ListView '{0}' - {1}",
                    this.AssociatedObject.Name, Enum.GetName(typeof(Key), this.Key));
                return;
            }

            var keybinding = new KeyBinding(this.Command, new KeyGesture(this.Key, this.ModifierKeys))
            {
                CommandParameter = this.AssociatedObject
            };
            this.AssociatedObject.InputBindings.Add(keybinding);
            _keyBinding = keybinding;
        }

        /// <summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
        /// </summary>
        /// <remarks>
        /// Override this to unhook functionality from the AssociatedObject.
        /// </remarks>
        protected override void OnDetaching()
        {
            if (_keyBinding != null)
            {
                this.AssociatedObject.InputBindings.Remove(_keyBinding);
                _keyBinding = null;
            }
            base.OnDetaching();
        }
    }
}
